﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Globalization;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;


namespace oled
{
    class Oled_Drive
    {
        public static int OLED_DPI = 4;
        public static bool Align_Mode = OLED_Align_Mode.Little_endian;
        public static OLED_Scan_Mode Scan_Mode = OLED_Scan_Mode.VertiByte_HoriScan;
        
        #region 本区域内 类、方法废弃 刷新速度慢

        //private class Pixel
        //{
        //    public Rectangle Draw;
        //    public Rectangle Fill;
        //    public Pixel()
        //    {
        //    }
        //    public Pixel(Rectangle RDraw, Rectangle RFill)
        //    {
        //        Draw = RDraw;
        //        Fill = RFill;
        //    }

        //}

        //private static Pixel Set_Pos(int x, int y, int dpi)
        //{
        //    x *= dpi;
        //    y *= dpi;
        //    Rectangle Framework = new Rectangle(new Point(x, y), new Size(dpi, dpi));
        //    Rectangle Point = new Rectangle(new Point(x + 1, y + 1), new Size(dpi - 1, dpi - 1));
        //    Pixel Pixel = new Pixel(Framework, Point);

        //    return Pixel;
        //}

        //private static void DrawPoint(int x, int y, Graphics Graphic)
        //{
        //    Pen pen = new Pen(Color.FromArgb(0, 0, 0), 1);
        //    Brush brush = new SolidBrush(Color.FromArgb(255, 255, 255));
        //    Pixel point = Set_Pos(x, y, OLED_DPI);

        //    Graphic.DrawRectangle(pen, point.Draw);
        //    Graphic.FillRectangle(brush, point.Fill);
        //}

        ////绘制方式 列行式
        //private static void VH_Mode(int x, int y, Byte data, Graphics Graphic)
        //{
        //    for (int ty = 0; ty < 8; ty++)
        //    {
        //        bool draw = (data & 0x01) == 1;
        //        if (draw)
        //        {
        //            DrawPoint(x, ty + y, Graphic);
        //        }
        //        data = (Byte)(data >> 1);
        //    }
        //}
        
        ////绘制方式 行列式
        //private static void HV_Mode(int x, int y, Byte data, Graphics Graphic)
        //{
        //    for (int tx = 0; tx < 8; tx++)
        //    {
        //        bool draw = (data & 0x01) == 1;
        //        if (draw)
        //        {
        //            DrawPoint(tx + x, y, Graphic);
        //        }
        //        data = (Byte)(data >> 1);
        //    }
        //}
        #endregion

        #region 底层模拟 OLED绘制 

        //生成一个窗口
        private static Rectangle Set_Windows(int x, int y, int sx, int sy)
        {
            Rectangle Framework = new Rectangle(new Point(x, y), new Size(sx, sy));

            return Framework;
        }

        //生成一个像素点
        private static Rectangle PixelPoint(int x, int y)
        {
            x *= OLED_DPI;
            y *= OLED_DPI;
            return new Rectangle(new Point(x + 1, y + 1), new Size(OLED_DPI - 1, OLED_DPI - 1));
        }

        //获取绘制点图
        private static List<Rectangle> GetPoints_VH_Mode(OLED_Param oled)
        {
            List<Rectangle> PointList = new List<Rectangle>();

            bool[] draw = Bit.Bool_Array(oled.data, Align_Mode);

            PointList.Clear();

            for (int y = 0; y < 8; y++)
            {
                if (draw[y])
                {
                    Rectangle point = PixelPoint(oled.X, y + oled.Y);
                    PointList.Add(point);
                }
            }

            return PointList;
        }

        //获取绘制点图
        private static List<Rectangle> GetPoints_HV_Mode(OLED_Param oled)
        {
            List<Rectangle> PointList = new List<Rectangle>();

            bool[] draw = Bit.Bool_Array(oled.data, Align_Mode);

            PointList.Clear();

            for (int x = 0; x < 8; x++)
            {
                if (draw[x])
                {
                    Rectangle point = PixelPoint(x + oled.X, oled.Y);
                    PointList.Add(point);
                }
            }

            return PointList;
        }

        //绘制方式 列行式
        private static void VH_Mode(OLED_Param oled)
        {
            Clear(oled.X, oled.Y, 1, 8, oled.Graphic);

            Rectangle[] points = GetPoints_VH_Mode(oled).ToArray();

            if (points.Length != 0)
            {

                Brush brush = new SolidBrush(Color.FromArgb(255, 255, 255));

                oled.Graphic.FillRectangles(brush, points);
            }
        }

        //绘制方式 行列式
        private static void HV_Mode(OLED_Param oled)
        {

            Rectangle[] points = GetPoints_HV_Mode(oled).ToArray();

            Clear(oled.X, oled.Y, 1, 8, oled.Graphic);


            if (points.Length != 0)
            {

                Brush brush = new SolidBrush(Color.FromArgb(255, 255, 255));

                oled.Graphic.FillRectangles(brush, points);
            }
        }

        //显示一个字节数据
        private static void DrawByte(int x, int y, Byte data, Graphics Graphic)
        {
            OLED_Param oled = new OLED_Param(x, y, data, Graphic);
            switch (Scan_Mode)
            {
                //case Oled_Mode.Vertical_scan:
                //    break;
                //case Oled_Mode.Horizontal_scan:
                //    break;
                case OLED_Scan_Mode.VertiByte_HoriScan:
                    VH_Mode(oled);
                    break;
                case OLED_Scan_Mode.HoriByte_Vertiscan:
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region 底层驱动 OLED屏幕参数设置

        //设置像素点大小 适应屏幕
        public static void Set_DPI(int height, int width)
        {
            if (height >= 240 || width >= 240)
            {
                OLED_DPI = 3;
            }
            else if (height >= 128 || width >= 128)
            {
                OLED_DPI = 4;
            }
            else
            {
                OLED_DPI = 4;
            }
        }

        //设置窗口大小 分辨率越低，尽量调大窗口
        public static void Set_PaintPanel(ref int in_h, ref int in_w)
        {
            in_w = in_w * OLED_DPI;
            in_h = in_h * OLED_DPI;
        }

        #endregion

        #region 顶层驱动/接口 

        public static void DrawBMP1(int Pos_x, int Pos_y, Byte[] bmp, int height, int width, Graphics Graphic)
        {
            OLED_Param oled;
            int x = 0, y = 0, i = 0;
            Rectangle[] points;
            List<Rectangle> PointList = new List<Rectangle>();
            PointList.Clear();
            Clear(Pos_x, Pos_y, width, height, Graphic);
            Byte[] line = new Byte[width];
            int loop = height / 8;

            if (height % 8 != 0) loop++;


            for (int j = 1; j <= loop; j++)
            {
                Array.Copy(bmp, width * (j - 1), line, 0, width);

                for (x = 0, i = 0; i < width; x++, i++)
                {
                    oled = new OLED_Param(Pos_x + x, Pos_y + y, line[i]);
                    PointList.AddRange(GetPoints_VH_Mode(oled));
                }
                y += 8;
            }

            points = PointList.ToArray();

            if (points.Length != 0)
            {
                Brush brush = new SolidBrush(Color.FromArgb(255, 255, 255));
                Graphic.FillRectangles(brush, points);
            }
        }

        public static void ShowBMP(int Pos_x, int Pos_y, Byte[] bmp, int height, int width, Graphics Graphic)
        {
            OLED_Param oled;
            int x = 0, y = 0;
            Rectangle[] points;
            List<Rectangle> PointList = new List<Rectangle>();
            PointList.Clear();
            Clear(Pos_x, Pos_y, width, height, Graphic);

            for (int i = 0; i < bmp.Length; i++)
            {
                oled = new OLED_Param(Pos_x + x, Pos_y + y, bmp[i]);
                PointList.AddRange(GetPoints_VH_Mode(oled));
                x++;
                if (x % width == 0)
                {
                    x = 0;
                    y += 8;
                }
            }

            points = PointList.ToArray();

            if (points.Length != 0)
            {
                Brush brush = new SolidBrush(Color.FromArgb(255, 255, 255));
                Graphic.FillRectangles(brush, points);
            }
        }

        //显示一个字符
        public static void ShowChar(int x, int y, Byte data, Graphics Graphic)
        {
            int index = data - ' ';

            index *= 6;

            for (int i = 0; i < 6; i++)
            {
                DrawByte(x+i, y, Fonts.F6X8[index+i], Graphic);
            }
        }

        //显示一个字符串
        public static void ShowString(int x, int y, string text, Graphics Graphic)
        {
            int lenth = text.Length;

            Byte[] data = System.Text.Encoding.Default.GetBytes(text); 
            for (int loop = 0; loop < lenth; loop++)
            {
                ShowChar(x, y, data[loop], Graphic);
                x += 6;
            }
        }

        //清屏
        public static void Clear(PictureBox oled)
        {
            Graphics Graphic = oled.CreateGraphics();
            Graphic.Clear(Color.Black);
        }

        //清屏指定大小窗口
        public static void Clear(int x, int y, int sx, int sy, Graphics Graphic)
        {
            Brush brush = new SolidBrush(Color.Black);

            Rectangle windows = Set_Windows(x * OLED_DPI, y * OLED_DPI, sx * OLED_DPI, sy * OLED_DPI);

            Graphic.FillRectangle(brush, windows);
        }

        #endregion
    }
}
